import { isEqual } from 'lodash'

class ExprssionUtil {
  // 构造函数
  constructor(specific, data, levelCode, loginUser) {
    // 表达式配置信息
    this.specific = specific
    // 数据信息
    this.data = data
    // 机构levelCode
    this.levelCode = levelCode
    // 登录用户信息
    this.loginUser = loginUser
  }

  // 获取用户信息
  getLoginUser (code) {
    let userinfo = this.loginUser
    if (code == 'levelCode') {
      return userinfo.depts.map(item => {
        return item[code]
      })
    } else if (code == 'unitUserId') {
      return userinfo[code]
    } else {
      return userinfo[code]
    }
  }

  // 判断器
  excute () {
    // 循环条件项获取每个条件项的布尔值
    let specarr = this.specific.conditions.map(con => {
      // 循环条件组获取每个条件的布尔值
      let conarr = con.specifics.map(spec => {
        // 判断是否为机构
        if (spec.levelCode) {
          if (spec.dataType == 'array') {
            return this.unitsExcutor(spec)
          } else if (spec.dataType == 'unit') {
            let bool = this.unitExcutor(spec.levelCode, this.getLoginUser('levelCode'))
            return spec.operator == 'like' ? bool : !bool
          }
        } else {
          // 将json生成表达式运算更具数据类型进行运算
          if (spec.dataType == 'num' || spec.dataType == 'money') { // 数字和金额
            return this.numberExcutor(spec)
          } else if (spec.dataType == 'string') { // 字符串
            return this.stringExcutor(spec)
          } else if (spec.dataType == 'array') { // 数组
            return this.arrayExcutor(spec)
          } else if (spec.dataType == 'date') { // 日期
            return this.dateExcutor(spec)
          } else if (spec.dataType == 'user') {
            let bool = this.userExcutor(spec.value, this.getLoginUser('id').split(','))
            return spec.operator == 'like' ? bool : !bool
          } else if (spec.dataType == 'role') {
            let bool = this.roleExcutor(spec.value, this.getLoginUser('roleIds').split(','))
            return spec.operator == 'like' ? bool : !bool
          }
        }
      })
      return this.operators(con.type, conarr)
    })
    return this.operators(this.specific.type, specarr)
  }

  // 机构角色人员综合判断
  unitUserRoleExcutor (unit, user, role) {
    let units = this.unitExcutor(unit[1], unit[0])
    let users = this.userExcutor(user[0], user[1])
    let roles = this.roleExcutor(role[0], role[1])
    let arr = [units, users, roles].filter(item => { return item !== 'empty' })
    if (arr.length > 0) {
      return arr.some(e => e)
    } else {
      return true
    }
  }

  // 机构
  // arr2表示选择的值，arr1表示条件值
  unitExcutor (arr1 = [], arr2 = []) {
    if (arr1.length == 0 || arr2.length == 0) {
      return 'empty'
    } else {
      return this.levelFun(arr1, arr2)
    }
  }

  // 角色
  // arr1表示选择的值，arr2表示条件值
  roleExcutor (arr1 = [], arr2 = []) {
    if (arr1.length == 0 || arr2.length == 0) {
      return 'empty'
    } else {
      return arr2.map(item => {
        return arr1.includes(item)
      }).some(e => e)
    }
  }

  // 用户
  // arr1表示选择的值，arr2表示条件值
  userExcutor (arr1 = [], arr2 = []) {
    if (arr1.length == 0 || arr2.length == 0) {
      return 'empty'
    } else {
      return arr1.map(item => {
        return arr2.includes(item)
      }).some(e => e)
    }
  }

  // 业务机构
  unitsExcutor (spec) {
    // 按同一规则排序数组
    let arr1 = this.levelCode || [] // 选择的levelCode
    let arr2 = spec.levelCode || [] // 条件的levelCode
    if (spec.operator == 'equal') { // 等于
      return isEqual(arr1, arr2)
    } else if (spec.operator == 'notequal') { // 不等于
      return !isEqual(arr1, arr2)
    } else if (spec.operator == 'inc') { // 包含
      if (arr1.length > 0) {
        return this.levelFun(arr1, arr2)
      } else {
        return false
      }
    } else if (spec.operator == 'like') { // 属于
      if (arr1.length > 0) {
        return this.levelFun(arr2, arr1)
      } else {
        return false
      }
    } else if (spec.operator == 'notinc') { // 不包含
      if (arr1.length > 0) {
        return !(this.levelFun(arr1, arr2))
      } else {
        return false
      }
    } else if (spec.operator == 'notlike') { // 不属于
      if (arr1.length > 0) {
        return !(this.levelFun(arr2, arr1))
      } else {
        return false
      }
    } else if (spec.operator == 'null') {
      return !arr1.length > 0
    } else if (spec.operator == 'notnull') {
      return !!arr1.length > 0
    }
  }

  // arr1包含arr2返回true
  levelFun (arr1, arr2) {
    // 判断长度
    return arr1.map(a1 => {
      return arr2.map(a2 => {
        // 判断长度小于等于
        if (a1.length <= a2.length) {
          return a2.substr(0, a1.length) == a1
        } else {
          return false
        }
      }).every(e => e)
    }).some(e => e)
  }

  // 数字和金额
  numberExcutor (spec) {
    // 是否为空
    if (spec.operator == 'null') {
      return this.data[spec.filed] == 0 ? !!this.data[spec.filed] : !this.data[spec.filed]
    } else if (spec.operator == 'notnull') {
      return this.data[spec.filed] == 0 ? !this.data[spec.filed] : !!this.data[spec.filed]
    } else {
      if (this.data[spec.filed] || this.data[spec.filed] == 0) {
        return eval(Number(this.data[spec.filed]) + this.getJudge(spec.operator) + Number(spec.value))
      } else {
        return false
      }
    }
  }

  // 字符串
  stringExcutor (spec) {
    let str1 = this.data?.[spec.filed]
    let str2 = spec.value
    // 等于和不等于
    if (str1) {
      if (spec.operator == 'equal') {
        return isEqual(str1, str2)
      } else if (spec.operator == 'notequal') {
        return !isEqual(str1, str2)
      } else if (spec.operator == 'inc') { // 包含
        return str1.includes(str2)
      } else if (spec.operator == 'notinc') { // 不包含
        return !str1.includes(str2)
      } else if (spec.operator == 'like') { // 属于
        return str2.includes(str1)
      } else if (spec.operator == 'notlike') { // 不属于
        return !str2.includes(str1)
      } else if (spec.operator == 'notnull') {
        return !!str1
      } else if (spec.operator == 'null') {
        return !str1
      }
    } else {
      if (spec.operator == 'null') {
        return !str1
      } else {
        return false
      }
    }
  }

  // 数组
  arrayExcutor (spec) {
    // 按同一规则排序数组
    // arr1表示选择的数据，arr2表示条件数据
    let arr1 = this.data[spec.filed] ? [...this.data[spec.filed]].sort((a, b) => { return a - b }) : []
    let arr2 = spec.value ? [...spec.value].sort((a, b) => { return a - b }) : []
    // 等于
    if (spec.operator == 'equal') {
      return isEqual(arr1, arr2)
    } else if (spec.operator == 'notequal') { // 不等于
      return !isEqual(arr1, arr2)
    } else if (spec.operator == 'inc') { // 包含
      return arr2.every(a => {
        return arr1.includes(a)
      })
    } else if (spec.operator == 'like') { // 属于
      if (arr1.length > 0) {
        return arr1.every(a => {
          return arr2.includes(a)
        })
      } else {
        return false
      }
    } else if (spec.operator == 'notinc') { // 不包含
      return !(arr2.every(a => {
        return arr1.includes(a)
      }))
    } else if (spec.operator == 'notlike') { // 不属于
      return !(arr1.every(a => {
        return arr2.includes(a)
      }))
    } else if (spec.operator == 'null') { // 为空
      return !arr1.length > 0
    } else if (spec.operator == 'notnull') { // 不为空
      return !!arr1.length > 0
    }
  }

  // 日期

  dateExcutor (spec) {
    let time = new Date(this.data[spec.filed]).getTime()
    if (!time) {
      if (spec.operator == 'null') {
        return !time
      } else {
        return false
      }
    } else {
      // 等于、小于、小于等于、不等于、大于等于、大于
      if (spec.operator == 'equal' || spec.operator == 'lt' || spec.operator == 'datelt' || spec.operator == 'notequal' || spec.operator == 'dategt' || spec.operator == 'gt') {
        return eval(time + this.getJudge(spec.operator) + new Date(spec.value).getTime())
      } else if (spec.operator == 'like') { // 属于
        return time >= new Date(spec.value[0]).getTime() && time <= new Date(spec.value[1]).getTime()
      } else if (spec.operator == 'notlike') { // 不属于
        return !(time >= new Date(spec.value[0]).getTime() && time <= new Date(spec.value[1]).getTime())
      } else if (spec.operator == 'notnull') {
        return !!time
      }
    }
  }

  // 判断条件转换
  getJudge (type) {
    if (type == 'lt') { // 小于
      return '<'
    } else if (type == 'datelt') { // 小于等于
      return '<='
    } else if (type == 'equal') { // 等于
      return '=='
    } else if (type == 'notequal') { // 不等于
      return '!=='
    } else if (type == 'dategt') { // 大于等于
      return '>='
    } else if (type == 'gt') { // 大于
      return '>'
    }
  }

  operators (type, arr) {
    // 条件为1则是且条件 否则则是或条件
    if (type == '1') {
      // 且条件时满足所有条件返回true
      return arr.every(bool => { return bool })
    } else {
      // 或条件时满足一个即返回true
      return arr.some(bool => { return bool })
    }
  }
}
export default ExprssionUtil
